#include "s3e.h"
#include "Iw2D.h"
#include "engine.h"
#include <list>
#include <vector>
#include "ui_menu.h"
#include "ui_page.h"
#include "ui_widgets.h"

extern char g_StringBuffer[256];

namespace UI
{

Widget::Widget( CIwFVec2 a_Position )
	: m_Position(a_Position)
	, m_AbsolutePosition( int16(Iw2DGetSurfaceWidth() * m_Position.x), int16(Iw2DGetSurfaceHeight() * m_Position.y) )
	, m_Pressed(false)
{
	m_OnDownMethod = NULL;
	m_OnUpMethod = NULL;
}

Widget::~Widget()
{
	
}

UI::Menu* Widget::GetParentMenu()
{
	return m_ParentMenu;
}

void Widget::SetOnDownMethod( void (*a_Method)( Widget* ) )
{
	m_OnDownMethod = a_Method;
}

void Widget::SetOnUpMethod( void (*a_Method)( Widget* ) )
{
	m_OnUpMethod = a_Method;
}

void Widget::SetParentMenu( UI::Menu* a_Menu )
{
	m_ParentMenu = a_Menu;
}

Button::Button( CIwFVec2 a_Position, CIwFVec2 a_Size, const char* a_ImageNormal, const char* a_ImageDown, void (*a_OnDownMethod)( Widget* ) /*= NULL*/, void (*a_OnUpMethod)( Widget* ) /*= NULL*/ )
	: Widget(a_Position)
	, m_Size(a_Size)
	, m_AbsoluteSize( int16(Iw2DGetSurfaceWidth() * m_Size.x), int16(Iw2DGetSurfaceHeight() * m_Size.y) )
	, m_ImageNormal(Iw2DCreateImageResource(a_ImageNormal))
	, m_ImageDown(Iw2DCreateImageResource(a_ImageDown))
{
	SetOnDownMethod(a_OnDownMethod);
	SetOnUpMethod(a_OnUpMethod);
}

Button::~Button()
{
	if (m_ImageNormal)
	{
		delete m_ImageNormal;
		m_ImageNormal = NULL;
	}
	if (m_ImageDown)
	{
		delete m_ImageDown;
		m_ImageDown = NULL;
	}
}

void Button::Update( float a_DT )
{
	float touchX = (float)s3ePointerGetTouchX(0);
	float touchY = (float)s3ePointerGetTouchY(0);
	s3ePointerState touchState = s3ePointerGetState( s3ePointerButton(0) );
	CIwSVec2 TouchStart = m_ParentMenu->GetTouchStart();
	
	if ( touchX >= m_AbsolutePosition.x && touchX <= m_AbsolutePosition.x + m_AbsoluteSize.x &&
		 touchY >= m_AbsolutePosition.y && touchY <= m_AbsolutePosition.y + m_AbsoluteSize.y &&
		 TouchStart.x >= m_AbsolutePosition.x && TouchStart.x <= m_AbsolutePosition.x + m_AbsoluteSize.x &&
		 TouchStart.y >= m_AbsolutePosition.y && TouchStart.y <= m_AbsolutePosition.y + m_AbsoluteSize.y )
	{
		if ( touchState == S3E_POINTER_STATE_PRESSED )
		{
			m_Pressed = true;
			if (m_OnDownMethod != NULL)
			{
				m_OnDownMethod(this);
			}
		}
		else if ( touchState == S3E_POINTER_STATE_DOWN )
		{
			// Do whatever while the button is being pressed down.
			m_Pressed = true;
		}
		else if ( touchState == S3E_POINTER_STATE_RELEASED )
		{
			m_Pressed = false;
			if (m_OnUpMethod != NULL)
			{
				m_OnUpMethod(this);
			}
		}
	}
	else
	{
		m_Pressed = false;
	}
}

void Button::Render()
{
	// Render the button.
	if (m_Pressed)
	{
		Iw2DDrawImage(m_ImageDown, m_AbsolutePosition, m_AbsoluteSize);
	}
	else
	{
		Iw2DDrawImage(m_ImageNormal, m_AbsolutePosition, m_AbsoluteSize);
	}
}

void Button::Delete()
{
	if (m_ImageDown)
	{
		delete m_ImageDown;
		m_ImageDown = NULL;
	}
	if (m_ImageNormal)
	{
		delete m_ImageNormal;
		m_ImageNormal = NULL;
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Slider::Slider( CIwFVec2 a_Position, 
				CIwFVec2 a_Size, 
				const char* a_ImageBase,
				float& a_Variable,
				float a_MinVal, 
				float a_MaxVal, 
				bool a_Reversed /*= false*/,
				void (*a_OnDownMethod)( Widget* )/* = NULL*/, 
				void (*a_OnUpMethod)( Widget* )/* = NULL*/ )
	: Widget(a_Position)
	, m_Size(a_Size)
	, m_AbsoluteSize( int16(Iw2DGetSurfaceWidth() * m_Size.x), int16(Iw2DGetSurfaceHeight() * m_Size.y) )
	, m_Variable(a_Variable)
	, m_MinVal(a_MinVal)
	, m_MaxVal(a_MaxVal)
	, m_Reversed(a_Reversed)
{
	SetOnDownMethod(a_OnDownMethod);
	SetOnUpMethod(a_OnUpMethod);

	sprintf(g_StringBuffer, "%s_l", a_ImageBase);
	m_ImageLeft = Iw2DCreateImageResource(g_StringBuffer);

	sprintf(g_StringBuffer, "%s_r", a_ImageBase);
	m_ImageRight = Iw2DCreateImageResource(g_StringBuffer);

	sprintf(g_StringBuffer, "%s_c", a_ImageBase);
	m_ImageCenter = Iw2DCreateImageResource(g_StringBuffer);

	sprintf(g_StringBuffer, "%s_d", a_ImageBase);
	m_ImageSliderDown = Iw2DCreateImageResource(g_StringBuffer);

	sprintf(g_StringBuffer, "%s_u", a_ImageBase);
	m_ImageSliderUp = Iw2DCreateImageResource(g_StringBuffer);

	const float w = (float)Iw2DGetSurfaceWidth(), h = (float)Iw2DGetSurfaceHeight();
	m_SideSize = (m_AbsoluteSize.y / float(m_ImageLeft->GetHeight())) * float(m_ImageLeft->GetWidth());

	const float sliderScale = ((float)m_AbsoluteSize.y / m_ImageSliderUp->GetHeight());
	m_SliderSize = CIwSVec2( int16(m_ImageSliderUp->GetWidth() * sliderScale), int16(m_ImageSliderDown->GetHeight() * sliderScale) );

	int dbg = 0;
}

Slider::~Slider()
{
	if (m_ImageSliderDown)
	{
		delete m_ImageSliderDown;
		m_ImageSliderDown = NULL;
	}
	if (m_ImageSliderUp)
	{
		delete m_ImageSliderUp;
		m_ImageSliderUp = NULL;
	}
	if (m_ImageLeft)
	{
		delete m_ImageLeft;
		m_ImageLeft = NULL;
	}
	if (m_ImageRight)
	{
		delete m_ImageRight;
		m_ImageRight = NULL;
	}
	if (m_ImageCenter)
	{
		delete m_ImageCenter;
		m_ImageCenter = NULL;
	}
}

void Slider::Update( float a_DT )
{
	float touchX = (float)s3ePointerGetTouchX(0);
	float touchY = (float)s3ePointerGetTouchY(0);
	s3ePointerState touchState = s3ePointerGetState( s3ePointerButton(0) );
	CIwSVec2 TouchStart = m_ParentMenu->GetTouchStart();

	if ( touchX >= m_AbsolutePosition.x && touchX <= m_AbsolutePosition.x + m_AbsoluteSize.x &&
		touchY >= m_AbsolutePosition.y && touchY <= m_AbsolutePosition.y + m_AbsoluteSize.y &&
		TouchStart.x >= m_AbsolutePosition.x && TouchStart.x <= m_AbsolutePosition.x + m_AbsoluteSize.x &&
		TouchStart.y >= m_AbsolutePosition.y && TouchStart.y <= m_AbsolutePosition.y + m_AbsoluteSize.y )
	{
		if ( touchState == S3E_POINTER_STATE_PRESSED )
		{
			m_Pressed = true;
			if (m_OnDownMethod != NULL)
			{
				m_OnDownMethod(this);
			}
		}
		else if ( touchState == S3E_POINTER_STATE_DOWN )
		{
			float percent = (touchX - m_AbsolutePosition.x - m_SideSize) / (m_AbsoluteSize.x - (m_SideSize * 2));
	
			percent = (percent < 0.0f)?(0.0f):((percent > 1.0f)?(1.0f):(percent));

			m_Variable = m_MinVal + ((m_MaxVal - m_MinVal) * percent);
			if (m_Reversed)
				m_Variable = (m_MaxVal + m_MinVal) - m_Variable;
			m_Pressed = true;

			Engine::GetSingletonPtr()->UpdateMusicVolume();
		}
		else if ( touchState == S3E_POINTER_STATE_RELEASED )
		{
			m_Pressed = false;
			if (m_OnUpMethod != NULL)
			{
				m_OnUpMethod(this);
			}
		}
	}
	else
	{
		m_Pressed = false;
	}
}

void Slider::Render()
{
	CIwSVec2 SideSize = CIwSVec2( int16(m_SideSize), int16(m_SideSize) );
	Iw2DDrawImage(m_ImageLeft, m_AbsolutePosition, SideSize);
	Iw2DDrawImage(m_ImageRight, m_AbsolutePosition + CIwSVec2( int16(m_AbsoluteSize.x - m_SideSize), 0), SideSize);

	SideSize.y = 0;
	Iw2DDrawImage(m_ImageCenter, m_AbsolutePosition + SideSize, m_AbsoluteSize - CIwSVec2(SideSize.x * 2, 0));

	float sliderPos = ((m_Variable - m_MinVal) / (m_MaxVal - m_MinVal));
	if (m_Reversed)
		sliderPos = 1.0f - sliderPos;
	// Render the button.
	CIwFVec2 SliderPosition(m_AbsoluteSize.x - (m_SideSize * 2), m_AbsoluteSize.y);
	SliderPosition = SliderPosition * sliderPos;
	if (m_Pressed)
	{
		Iw2DDrawImage(m_ImageSliderDown, CIwSVec2( int16(m_AbsolutePosition.x + m_SideSize + SliderPosition.x - (float(m_SliderSize.x) / 2)), int16(m_AbsolutePosition.y) ), m_SliderSize);
	}
	else
	{
		Iw2DDrawImage(m_ImageSliderUp, CIwSVec2( int16(m_AbsolutePosition.x + m_SideSize + SliderPosition.x - (float(m_SliderSize.x) / 2)), int16(m_AbsolutePosition.y) ), m_SliderSize);
	}
}

void Slider::Delete()
{
	if (m_ImageSliderDown)
	{
		delete m_ImageSliderDown;
		m_ImageSliderDown = NULL;
	}
	if (m_ImageSliderUp)
	{
		delete m_ImageSliderUp;
		m_ImageSliderUp = NULL;
	}
	if (m_ImageLeft)
	{
		delete m_ImageLeft;
		m_ImageLeft = NULL;
	}
	if (m_ImageRight)
	{
		delete m_ImageRight;
		m_ImageRight = NULL;
	}
	if (m_ImageCenter)
	{
		delete m_ImageCenter;
		m_ImageCenter = NULL;
	}
}

const float& Slider::GetVariableRef()
{
	return m_Variable;
}


Image::Image( CIwFVec2 a_Position, CIwFVec2 a_Size, const char* a_Image )
	: Widget(a_Position)
	, m_Size(a_Size)
	, m_AbsoluteSize( int16(Iw2DGetSurfaceWidth() * m_Size.x), int16(Iw2DGetSurfaceHeight() * m_Size.y) )
	, m_Image(NULL)
{
	m_Image = Iw2DCreateImageResource(a_Image);
}

Image::~Image()
{
	Delete();
}

void Image::Update( float a_DT )
{

}

void Image::Render()
{
	if (m_Image)
	{
		Iw2DSetColour(0xffffffff);
		Iw2DDrawImage(m_Image, m_AbsolutePosition, m_AbsoluteSize);
	}
}

void Image::Delete()
{
	if (m_Image)
		delete m_Image;
	m_Image = NULL;
}

}